/*
 * Copyright (C) 2023 Realtek Semiconductor Corp.
 * All Rights Reserved.
 *
 * This program is the proprietary software of Realtek Semiconductor
 * Corporation and/or its licensors, and only be used, duplicated,
 * modified or distributed under the authorized license from Realtek.
 *
 * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
 * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
 *
 * Purpose : Definition of ME handler: Sub FTTR Unit  (65507)
 *
 * Feature : The file includes the following modules and sub-modules
 *           (1) ME handler: SUB Sub Unit  (65507)
 */

#include "app_basic.h"
#include "omci_task.h"
#include "feature_mgmt.h"

MIB_TABLE_INFO_T gMibSubFttrUnitTableInfo;
MIB_ATTR_INFO_T  gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ATTR_NUM];
MIB_TABLE_SUB_FTTR_UNIT_T gMibSubFttrUnitDefRow;
MIB_TABLE_OPER_T gMibSubFttrUnitOper;

static GOS_ERROR_CODE omci_mib_sub_fttr_unit_reset(UINT32 args_num, ...)
{
    INT32 sfuId, mfuPortId;
    MIB_TABLE_SUB_FTTR_UNIT_T mibSubFttrUnit;
    omci_dm_fttr_onu_info_t dmFttrOnuInfo;

    memset(&dmFttrOnuInfo, 0, sizeof(omci_dm_fttr_onu_info_t));

    for(mfuPortId = 0; mfuPortId < FTTR_P2MP_MFU_POT_NUM;mfuPortId++)
    {
        for(sfuId = 0; sfuId < FTTR_P2MP_SFU_NUM;sfuId++)
        {    
            MIB_Default(MIB_TABLE_SUB_FTTR_UNIT_INDEX, &mibSubFttrUnit, sizeof(MIB_TABLE_SUB_FTTR_UNIT_T));

            mibSubFttrUnit.EntityID         = (UINT16)((mfuPortId << 8) | (sfuId));
            OMCI_LOG(OMCI_LOG_LEVEL_INFO, "Resetting MIB: SUB FTTR UNIT EntityID:0x%04x", mibSubFttrUnit.EntityID);

            dmFttrOnuInfo.mfuPortId = mfuPortId;
            dmFttrOnuInfo.sfutId =  sfuId;          

            if(FAL_OK == feature_api(FEATURE_API_FTTR_P2MP_GET, 
                                OMCI_DM_FTTR_CMD_GET_ONU_INFO_OP_STATE, 
                                &dmFttrOnuInfo, 
                                sizeof(omci_dm_fttr_onu_info_t)))
            {
                mibSubFttrUnit.OpState = (OMCI_DM_FTTR_OP_STATE_EN == dmFttrOnuInfo.opState)  ?
                    OMCI_ME_ATTR_OP_STATE_ENABLED : OMCI_ME_ATTR_OP_STATE_DISABLED;
                
                mibSubFttrUnit.AdminState = (OMCI_DM_FTTR_OP_STATE_EN == dmFttrOnuInfo.opState)  ?
                    OMCI_ME_ATTR_ADMIN_STATE_UNLOCK : OMCI_ME_ATTR_ADMIN_STATE_LOCK;
      
            }

            if(FAL_OK == feature_api(FEATURE_API_FTTR_P2MP_GET, 
                                OMCI_DM_FTTR_CMD_GET_ONU_INFO_SN, 
                                &dmFttrOnuInfo, 
                                sizeof(omci_dm_fttr_onu_info_t)))
            {
                memcpy(&mibSubFttrUnit.SerialNum[0], &dmFttrOnuInfo.serialNum[0] ,OMCI_DM_FTTR_SN_LEN);
            }


            if(FAL_OK == feature_api(FEATURE_API_FTTR_P2MP_GET, 
                                OMCI_DM_FTTR_CMD_GET_ONU_INFO_FIBER_DISTANCE, 
                                &dmFttrOnuInfo, 
                                sizeof(omci_dm_fttr_onu_info_t)))
            {
                mibSubFttrUnit.FiberDistance = dmFttrOnuInfo.fiberDistance;
            }


            if(FAL_OK == feature_api(FEATURE_API_FTTR_P2MP_GET, 
                                OMCI_DM_FTTR_CMD_GET_ONU_INFO_MFU_RX_PWR, 
                                &dmFttrOnuInfo, 
                                sizeof(omci_dm_fttr_onu_info_t)))
            {
                // unit: dBu (dBm = 10*log(mW), dBu = 10*log(mw*10^3) = dBm+30), 0.002 dB resolution
                mibSubFttrUnit.MfuReceivedOpticalPwr = (INT16)((dmFttrOnuInfo.mfuReceivedOpticalPwr+30) * 500); 
            }

            GOS_ASSERT(GOS_OK == MIB_Set(MIB_TABLE_SUB_FTTR_UNIT_INDEX, &mibSubFttrUnit, sizeof(MIB_TABLE_SUB_FTTR_UNIT_T)));
            OMCI_MeOperCfg(MIB_TABLE_SUB_FTTR_UNIT_INDEX, NULL, &mibSubFttrUnit, MIB_ADD,
                omci_GetOltAccAttrSet(MIB_TABLE_SUB_FTTR_UNIT_INDEX, OMCI_ME_ATTR_ACCESS_SBC), OMCI_MSG_BASELINE_PRI_LOW);

        }

    }

    return GOS_OK;

}


GOS_ERROR_CODE omci_mib_sub_fttr_unit_drv_cfg(void              *pOldRow,
                            void            *pNewRow,
                            MIB_OPERA_TYPE  operationType,
                            MIB_ATTRS_SET   attrSet,
                            UINT32          pri)
{

    GOS_ERROR_CODE      ret = GOS_OK;
    MIB_TABLE_INDEX     tableIndex = MIB_TABLE_SUB_FTTR_UNIT_INDEX;
    omci_dm_fttr_onu_info_t dmFttrOnuInfo;
    MIB_TABLE_SUB_FTTR_UNIT_T    mibSubFttrUnit, *pMibSubFttrUnit;
    BOOL isUpdateMib = FALSE;

    // read out the instanceID
    pMibSubFttrUnit = (MIB_TABLE_SUB_FTTR_UNIT_T*)pNewRow;
    mibSubFttrUnit.EntityID = pMibSubFttrUnit->EntityID;

    memset(&dmFttrOnuInfo, 0, sizeof(omci_dm_fttr_onu_info_t));
    dmFttrOnuInfo.mfuPortId = (mibSubFttrUnit.EntityID & 0xFF00) >> 8;
    dmFttrOnuInfo.sfutId = mibSubFttrUnit.EntityID & 0xFF ;

    switch (operationType)
    {     
        case MIB_ADD:
            ret = mib_alarm_table_add(tableIndex, pNewRow);
            break;
        case MIB_DEL:
            ret = mib_alarm_table_del(tableIndex, pOldRow);
            break;
        case MIB_GET:
            ret = MIB_Get(tableIndex, &mibSubFttrUnit, sizeof(MIB_TABLE_SUB_FTTR_UNIT_T));
            if (GOS_OK != ret)
            {
                OMCI_LOG(OMCI_LOG_LEVEL_ERR, "Instance not found in %s: %s, 0x%x",
                    __FUNCTION__, MIB_GetTableName(tableIndex), mibSubFttrUnit.EntityID);

                return GOS_FAIL;
            }

            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX))
            {
                if(FAL_OK == feature_api(FEATURE_API_FTTR_P2MP_GET, 
                                    OMCI_DM_FTTR_CMD_GET_ONU_INFO_OP_STATE, 
                                    &dmFttrOnuInfo, 
                                    sizeof(omci_dm_fttr_onu_info_t)))
                {

                    mibSubFttrUnit.OpState = (OMCI_DM_FTTR_OP_STATE_EN == dmFttrOnuInfo.opState)  ?
                        OMCI_ME_ATTR_OP_STATE_ENABLED : OMCI_ME_ATTR_OP_STATE_DISABLED;
                    pMibSubFttrUnit->OpState = mibSubFttrUnit.OpState;                    
                }

            }

            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX))
            {
                if(FAL_OK == feature_api(FEATURE_API_FTTR_P2MP_GET, 
                                    OMCI_DM_FTTR_CMD_GET_ONU_INFO_SN, 
                                    &dmFttrOnuInfo, 
                                    sizeof(omci_dm_fttr_onu_info_t)))
                {
                    memcpy(&pMibSubFttrUnit->SerialNum[0], &dmFttrOnuInfo.serialNum[0] ,OMCI_DM_FTTR_SN_LEN);
                    memcpy(&mibSubFttrUnit.SerialNum[0], &dmFttrOnuInfo.serialNum[0] ,OMCI_DM_FTTR_SN_LEN);
                    isUpdateMib = TRUE;
                }
            }

            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX))
            {
                if(FAL_OK == feature_api(FEATURE_API_FTTR_P2MP_GET, 
                                    OMCI_DM_FTTR_CMD_GET_ONU_INFO_FIBER_DISTANCE, 
                                    &dmFttrOnuInfo, 
                                    sizeof(omci_dm_fttr_onu_info_t)))
                {

                    mibSubFttrUnit.FiberDistance = dmFttrOnuInfo.fiberDistance;
                    pMibSubFttrUnit->FiberDistance = dmFttrOnuInfo.fiberDistance;  
                    isUpdateMib = TRUE;
                }

            }

            if (MIB_IsInAttrSet(&attrSet, MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX))
            {
                if(FAL_OK == feature_api(FEATURE_API_FTTR_P2MP_GET, 
                                    OMCI_DM_FTTR_CMD_GET_ONU_INFO_MFU_RX_PWR, 
                                    &dmFttrOnuInfo, 
                                    sizeof(omci_dm_fttr_onu_info_t)))
                {
                    // unit: dBu (dBm = 10*log(mW), dBu = 10*log(mw*10^3) = dBm+30), 0.002 dB resolution    
                    mibSubFttrUnit.MfuReceivedOpticalPwr = (INT16)((dmFttrOnuInfo.mfuReceivedOpticalPwr+30) * 500);
                    pMibSubFttrUnit->MfuReceivedOpticalPwr = (INT16)((dmFttrOnuInfo.mfuReceivedOpticalPwr+30) * 500);  
                    isUpdateMib = TRUE;
                }
            }


            if(isUpdateMib)
            {
                if (GOS_OK != MIB_Set(tableIndex, &mibSubFttrUnit, sizeof(mibSubFttrUnit)))
                {
                    OMCI_LOG(OMCI_LOG_LEVEL_ERR, "Update MIB fail in %s: %s, 0x%x",
                        __FUNCTION__, MIB_GetTableName(tableIndex), mibSubFttrUnit.EntityID);
                }


            }
            break;

        default:
            break;
    }

    return GOS_OK;

}

GOS_ERROR_CODE omci_mib_sub_fttr_unit_dump_mib(void *pData, MIB_TABLE_INFO_T *pTblInfo)
{

    MIB_TABLE_SUB_FTTR_UNIT_T *pMibSubFttrUnit = (MIB_TABLE_SUB_FTTR_UNIT_T*)pData;

    OMCI_PRINT("EntityID: 0x%02x", pMibSubFttrUnit->EntityID);
    OMCI_PRINT("AdminState: %hhu", pMibSubFttrUnit->AdminState);
    OMCI_PRINT("OpState: %hhu", pMibSubFttrUnit->OpState);
    OMCI_PRINT("SerialNum: %c%c%c%c%02hhx%02hhx%02hhx%02hhx",
        pMibSubFttrUnit->SerialNum[0], pMibSubFttrUnit->SerialNum[1], pMibSubFttrUnit->SerialNum[2], pMibSubFttrUnit->SerialNum[3],
        pMibSubFttrUnit->SerialNum[4], pMibSubFttrUnit->SerialNum[5], pMibSubFttrUnit->SerialNum[6], pMibSubFttrUnit->SerialNum[7]);    
    OMCI_PRINT("FiberDistance: %hu", pMibSubFttrUnit->FiberDistance);
    OMCI_PRINT("MfuReceivedOpticalPwr: %hu", pMibSubFttrUnit->MfuReceivedOpticalPwr);

    return GOS_OK;
}


static GOS_ERROR_CODE omci_mib_sub_fttr_unit_alarm_handler(MIB_TABLE_INDEX  tableIndex,
                                            omci_alm_data_t     alarmData,
                                            omci_me_instance_t  *pInstanceID,
                                            BOOL                *pIsUpdated)
{
    mib_alarm_table_t	alarmTable;
    BOOL                isSuppressed;

    if (!pInstanceID || !pIsUpdated)
        return GOS_ERR_PARAM;

    *pIsUpdated = FALSE;

    // extract instanceID from alarm detail
    *pInstanceID = alarmData.almDetail;

    if (GOS_OK != mib_alarm_table_get(tableIndex, *pInstanceID, &alarmTable))
    {
        OMCI_LOG(OMCI_LOG_LEVEL_ERR, "Get alarm table fail: %s, 0x%x",
            MIB_GetTableName(tableIndex), *pInstanceID);

        return GOS_FAIL;
    }

    // update alarm status if it has being changed
    mib_alarm_table_update(&alarmTable, &alarmData, pIsUpdated);

    if (*pIsUpdated)
    {
        if (GOS_OK != mib_alarm_table_set(tableIndex, *pInstanceID, &alarmTable))
        {
            OMCI_LOG(OMCI_LOG_LEVEL_ERR, "Set alarm table fail: %s, 0x%x",
            MIB_GetTableName(tableIndex), *pInstanceID);
            
            return GOS_FAIL;
        }
        
    // check if notifications are suppressed by parent's admin state
    omci_is_notify_suppressed_by_circuitpack(0xFF, &isSuppressed);

    if (isSuppressed)
        *pIsUpdated = FALSE;

    }

    return GOS_OK;
}


static GOS_ERROR_CODE omci_mib_sub_fttr_unit_avc_cb(MIB_TABLE_INDEX     tableIndex,
                                            void                *pOldRow,
                                            void                *pNewRow,
                                            MIB_ATTRS_SET       *pAttrsSet,
                                            MIB_OPERA_TYPE      operationType)
{
    MIB_ATTR_INDEX      attrIndex;
    UINT32              i;
    MIB_ATTRS_SET       avcAttrSet;
    BOOL                isSuppressed;

    if (MIB_SET != operationType && MIB_ADD != operationType)
        return GOS_OK;

    if (!pNewRow || !pAttrsSet)
        return GOS_ERR_PARAM;

    // check if notifications are suppressed
    omci_is_notify_suppressed_by_circuitpack(0xFF, &isSuppressed);

    if (isSuppressed)
        MIB_ClearAttrSet(&avcAttrSet);
    else
    {
        avcAttrSet = *pAttrsSet;

        for (attrIndex = MIB_ATTR_FIRST_INDEX, i = 0;
                i < MIB_GetTableAttrNum(tableIndex); i++, attrIndex = MIB_ATTR_NEXT_INDEX(attrIndex))
        {
            if (!MIB_IsInAttrSet(pAttrsSet, attrIndex))
                continue;
        }
    }

    if (avcAttrSet != *pAttrsSet)
        *pAttrsSet = avcAttrSet;

    return GOS_OK;
}



GOS_ERROR_CODE mibTable_init(MIB_TABLE_INDEX tableId)
{
    UINT8 proprietary_mib_cb_bitmask = 0;
    UINT8 isIgnore = 0;

    if(GOS_OK == omci_ignore_mib_table_check(OMCI_ME_CLASS_SUB_FTTR_UNIT, OMCI_ME_CLASS_SUB_DEFAULT, &isIgnore))
    {
        if(isIgnore)
        {
            OMCI_PRINT("Ignore classId:%d", OMCI_ME_CLASS_SUB_FTTR_UNIT);
            return GOS_FAIL;
        }
    }

    gMibSubFttrUnitTableInfo.Name = "SUBFttrUnit";
    gMibSubFttrUnitTableInfo.ShortName = "SUBFttrUnit";
    gMibSubFttrUnitTableInfo.Desc = "SUB Fttr Unit";
    gMibSubFttrUnitTableInfo.ClassId = (UINT32)(OMCI_ME_CLASS_SUB_FTTR_UNIT);
    gMibSubFttrUnitTableInfo.InitType = (UINT32)(OMCI_ME_INIT_TYPE_ONU);
    gMibSubFttrUnitTableInfo.StdType = (UINT32)(OMCI_ME_TYPE_PROPRIETARY);
    gMibSubFttrUnitTableInfo.ActionType = (UINT32)(OMCI_ME_ACTION_SET | OMCI_ME_ACTION_GET);
    gMibSubFttrUnitTableInfo.pAttributes = &(gMibainFttrUnitAttrInfo[0]);
	gMibSubFttrUnitTableInfo.attrNum = MIB_TABLE_SUB_FTTR_UNIT_ATTR_NUM;
	gMibSubFttrUnitTableInfo.entrySize = sizeof(MIB_TABLE_SUB_FTTR_UNIT_T);
	gMibSubFttrUnitTableInfo.pDefaultRow = &gMibSubFttrUnitDefRow;

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].Name = "EntityID";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Name = "AdminState";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Name = "OpState";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].Name = "SerialNum";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].Name = "FiberDistance";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].Name = "MfuReceivedOpticalPwr";

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Entity ID";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Administrative state";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Operational state";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Serial Number";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "Fiber Distance";
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].Desc = "MFU Received OpticalPower";

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT16;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT8;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT8;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_STR;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT16;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].DataType = MIB_ATTR_TYPE_UINT16;

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].Len = 2;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Len = 1;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].Len = 1;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].Len = 8;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].Len = 2;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].Len = 2;

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = TRUE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].IsIndex = FALSE;

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].MibSave = TRUE;

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_HEX;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_HEX;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].OutStyle = MIB_ATTR_OUT_DEC;

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ | OMCI_ME_ATTR_ACCESS_WRITE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = OMCI_ME_ATTR_ACCESS_READ;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = MIB_ATTR_OUT_HEX;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = MIB_ATTR_OUT_DEC;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].OltAcc = MIB_ATTR_OUT_DEC;

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = TRUE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = TRUE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = TRUE;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].AvcFlag = FALSE;

    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ENTITYID_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_ADMINSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_OPSTATE_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_SN_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_FIBER_DISTANCE_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;
    gMibainFttrUnitAttrInfo[MIB_TABLE_SUB_FTTR_UNIT_MFU_RECEIVED_OPTICAL_PWR_INDEX - MIB_TABLE_FIRST_INDEX].OptionType = OMCI_ME_ATTR_TYPE_MANDATORY;


    memset(&gMibSubFttrUnitDefRow, 0x00, sizeof(gMibSubFttrUnitDefRow));

    memset(gMibSubFttrUnitDefRow.SerialNum, 0, MIB_TABLE_SUB_FTTR_UNIT_SN_LEN);
    gMibSubFttrUnitDefRow.SerialNum[MIB_TABLE_SUB_FTTR_UNIT_SN_LEN] = '\0';
    gMibSubFttrUnitDefRow.OpState = OMCI_ME_ATTR_OP_STATE_DISABLED;
    gMibSubFttrUnitDefRow.AdminState = OMCI_ME_ATTR_ADMIN_STATE_LOCK;

    memset(&gMibSubFttrUnitOper, 0x0, sizeof(MIB_TABLE_OPER_T));
    gMibSubFttrUnitOper.meOperDrvCfg = omci_mib_sub_fttr_unit_drv_cfg;
    gMibSubFttrUnitOper.meOperConnCheck = NULL;
    gMibSubFttrUnitOper.meOperDump = omci_mib_sub_fttr_unit_dump_mib;
    gMibSubFttrUnitOper.meOperConnCfg = NULL;
    gMibSubFttrUnitOper.meOperAlarmHandler = omci_mib_sub_fttr_unit_alarm_handler;
    gMibSubFttrUnitOper.meOperTestHandler = NULL;
    gMibSubFttrUnitOper.meOperCb[PROPRIETARY_MIB_CB_RESET] = omci_mib_sub_fttr_unit_reset;

    MIB_TABLE_SUB_FTTR_UNIT_INDEX = tableId;
    MIB_InfoRegister(tableId,&gMibSubFttrUnitTableInfo,&gMibSubFttrUnitOper);
    MIB_RegisterCallback(tableId, NULL, omci_mib_sub_fttr_unit_avc_cb);

    proprietary_mib_cb_bitmask = (1 << PROPRIETARY_MIB_CB_RESET);
    MIB_Proprietary_Reg(tableId, proprietary_mib_cb_bitmask);

    return GOS_OK;
}
